// 
// Author: damphat@gmail.com
//

#include "vn/DateTime.h"

#include <tchar.h>

static void CheckProps(const DateTime &a, int year, int month, int day, int hour, int minute, int second, int milisecond) {
	assert(a.GetYear()			== year);
	assert(a.GetMonth()			== month);
	assert(a.GetDay()			== day);
	assert(a.GetHour()			== hour);
	assert(a.GetMinute()		== minute);
	assert(a.GetSecond()		== second);
	assert(a.GetMillisecond()	== milisecond);
}

void DateTimeTest() {

	// Constructors
	{
		int year		= 2008;
		int month		= 10;
		int day			= 19;

		int hour		= 2;
		int minute		= 3;
		int second		= 45;
		int milisecond	= 999;

		DateTime	a( year, month, day, hour, minute, second, milisecond);
		CheckProps (a, year, month, day, hour, minute, second, milisecond);

		DateTime	b( year, month, day, hour, minute, second);
		CheckProps (b, year, month, day, hour, minute, second,          0);

		DateTime	c( year, month, day);
		CheckProps (c, year, month, day,    0,      0,      0,          0);

		DateTime	d(1500);
		CheckProps (d,    1,     1,   1,    0,      0,      1,        500);

		DateTime	e;
		CheckProps (e,    1,    1,   1,    0,      0,      0,          0);
	}

	// Constructors
	{
		DateTime a(1, 1, 1, 0, 0, 0, 900);
		assert(a.data == 900);

		DateTime b(1, 1, 1, 0, 0, 1, 900);
		assert(b.data == 900 + 1000);

		DateTime c(1, 1, 1, 0, 1, 1, 900);
		assert(c.data == 900 + 1000 + 60*1000);

		DateTime d(1, 1, 1, 1, 1, 1, 900);
		assert(d.data == 900 + 1000 + 60*1000 + 60*60*1000);

		DateTime e(1, 1, 2, 1, 1, 1, 900);
		assert(e.data == 900 + 1000 + 60*1000 + 60*60*1000 + 24*60*60*1000);

		DateTime f(1, 2, 2, 1, 1, 1, 900);
		assert(f.data == 900LL + 1000LL + 60*1000LL + 60*60*1000LL + 24*60*60*1000LL + 31*24*60*60*1000LL);

		DateTime g(2, 2, 2, 1, 1, 1, 900);
		assert(g.data == 900 + 1000 + 60*1000 + 60*60*1000 + 24*60*60*1000LL + 31*24*60*60*1000LL + 365*24*60*60*1000LL);
	}

	// const DateTime GetDate() const;
	{
		const DateTime a(2008, 10, 19, 2, 3, 45, 999);
		const DateTime b = a.GetDate();
		CheckProps (b, 2008, 10, 19, 0, 0, 0, 0);
	}

	// GetHour, GetMinute, GetSecond, GetMilisecond
	// GetYear, GetMonth, GetDate
	// .............................................

	// GetDayOfWeek, GetDayOfYear
	{
		const DateTime a(0);			//DateTime(1,1,1,0,0,0,0);

		assert(a.GetDayOfYear() == 1);	// from 1 to 365 or 366
		assert(a.GetDayOfWeek() == 1);	// from 0 to 6, 0 is Sunday

		const DateTime b(1,1,1+7,0,0,0,0);
		assert(b.GetDayOfYear() == 8);	// from 1 to 365 or 366
		assert(b.GetDayOfWeek() == 1);	// from 0 to 6, 0 is Sunday

	}

	// Testing day
	{
		const DateTime h(2008, 10, 19, 2, 3, 45, 999);
		assert(h.GetDayOfWeek()		== 0);		// Sunday
	}

	// ToString
	{
		const DateTime a(1901, 2, 3, 4, 5, 6, 7);
		assert(a.ToString()						== _T("03/02/1901 04:05:06.007"));
		assert(a.ToString(_T("dd/mm/yyyy"))		== _T("03/02/1901"));
		assert(a.ToString(_T("ddmmyyyy"))		== _T("03021901"));
		assert(a.ToString(_T("ddmmyy"))			== _T("030201"));
		assert(a.ToString(_T("hh:mm:ss"))		== _T("04:05:06"));
		assert(a.ToString(_T("hh:mm:ss.sss"))	== _T("04:05:06.007"));
	}

	// Now, Today
	{
		const DateTime a = DateTime::Now();			// Date and Time
		const DateTime b = DateTime::Today();		// Date only
		assert(a.GetYear() > 2007);
		assert(a.GetDate() == b);
	}

	// IsLeapYear, DaysInMonth
	{
		assert(DateTime::IsLeapYear(1999)==false);
		assert(DateTime::DaysInMonth(1999, 2) == 28);

		assert(DateTime::IsLeapYear(2000));
		assert(DateTime::DaysInMonth(2000, 2) == 29);
	}

	// Add or remove an amount of time
	// Duration between two DateTimes
	{
		const DateTime a(2008, 2, 27);
		const DateTime b(2008, 3, 1);
		const TimeSpan s(3,0,0,0);

		assert(a + s == b);		// DateTime + TimeSpan
		assert(b - s == a);		// DateTime - TimeSpan
		assert(b - a == s);		// DateTime - DateTime
	}

	// Compare two DateTime: return true
	{
		const DateTime a = DateTime::Now();
		const DateTime b = a;
		const DateTime c = a + 1;

		assert(a == b);
		assert(a != c);
		assert(a < c);
		assert(c > a);

		assert(a <= b);
		assert(a <= c);

		assert(b >= a);
		assert(c >= a);
	}

	// Compare two DateTime: return false
	{
		const DateTime a = DateTime::Now();
		const DateTime b = a + 1;
		const DateTime c = a;
		assert(! (a == b));
		assert(! (a != c));
		assert(! (a < c));
		assert(! (c > a));
		assert(! (a >= b));
		assert(! (b <= a));
	}

	// properties should return constant
	{
		// DateTime::Now().data = 0;
		// DateTime::Today().data = 0;
	}

	// Change property
	{
	}
}
